import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
import matplotlib as mpl
import random
from datetime import datetime, time, timedelta
import re

# 设置中文字体支持
try:
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Micro Hei', 'STXihei']
    plt.rcParams['axes.unicode_minus'] = False
    print("中文支持已启用")
except:
    print("中文支持设置失败，将使用英文")

# 读取Excel文件
file_path = 'E:/M/MathModel/23国赛C题/ds/附件5.xlsx'
sale = pd.read_excel(file_path, sheet_name='合并')
print("数据读取成功！总记录数:", len(sale))

# 转换日期格式
sale['销售日期'] = pd.to_datetime(sale['销售日期'])
# 过滤销售类型为"销售"的记录（排除退货）
sale = sale[sale['销售类型'] == '销售']


def parse_time(time_val):
    if pd.isna(time_val):
        return None

    # 如果已经是时间对象
    if isinstance(time_val, time):
        return time_val

    # 如果是datetime对象
    if isinstance(time_val, datetime):
        return time_val.time()

    # 如果是字符串
    if isinstance(time_val, str):
        # 尝试匹配 HH:MM:SS 格式
        match = re.match(r'(\d{1,2}):(\d{2}):(\d{2})', time_val)
        if match:
            return time(int(match.group(1)), int(match.group(2)), int(match.group(3)))

        # 尝试匹配 HH:MM 格式
        match = re.match(r'(\d{1,2}):(\d{2})', time_val)
        if match:
            return time(int(match.group(1)), int(match.group(2)))

        # 尝试匹配 HHMMSS 格式
        match = re.match(r'(\d{2})(\d{2})(\d{2})', time_val)
        if match:
            return time(int(match.group(1)), int(match.group(2)), int(match.group(3)))

    # 无法解析的情况
    return None


# 应用时间解析函数
sale['销售时间'] = sale['扫码销售时间'].apply(parse_time)

# 检查是否有无效时间
invalid_time_count = sale['销售时间'].isnull().sum()
if invalid_time_count > 0:
    print(f"警告: 有 {invalid_time_count} 条记录的销售时间无法解析")
    # 移除无效时间记录
    sale = sale.dropna(subset=['销售时间'])

print(f"处理后有效记录数: {len(sale)}")

# 随机选取4天（2020年7月1日到2023年6月30日之间）
start_date = pd.Timestamp('2020-07-01')
end_date = pd.Timestamp('2023-06-30')
date_range = pd.date_range(start_date, end_date, freq='D')

# 获取所有有销售记录的日期
available_dates = sale['销售日期'].dt.normalize().unique()

if len(available_dates) < 4:
    print(f"警告: 只有 {len(available_dates)} 天有销售记录，使用所有可用日期")
    selected_dates = available_dates[:4]
else:
    # 随机选择4天
    selected_dates = random.sample(list(available_dates), 4)

print("\n随机选择的4天日期:")
for date in selected_dates:
    print(date.strftime('%Y年%m月%d日'))

# 创建图表
plt.figure(figsize=(18, 12))

# 时间范围
hours = [time(h, 0) for h in range(9, 23)]

# 为每一天创建一个子图
for i, date in enumerate(selected_dates, 1):
    # 筛选当天的数据
    day_data = sale[sale['销售日期'].dt.normalize() == date]

    day_data = day_data[day_data['销售时间'].between(time(9, 0), time(22, 0))]

    # 按小时分组统计销售量
    day_data['小时'] = day_data['销售时间'].apply(lambda t: t.hour)
    hourly_sales = day_data.groupby('小时')['销量(千克)'].sum().reset_index()

    # 确保所有小时都在数据中
    all_hours = pd.DataFrame({'小时': range(9, 23)})
    hourly_sales = all_hours.merge(hourly_sales, on='小时', how='left').fillna(0)

    # 创建子图
    ax = plt.subplot(2, 2, i)

    # 绘制折线图
    ax.plot(hourly_sales['小时'], hourly_sales['销量(千克)'],
            marker='o', linestyle='-', linewidth=2.5, markersize=8, color='#d62728')

    # 添加数据点标签
    for _, row in hourly_sales.iterrows():
        ax.annotate(f'{row["销量(千克)"]:.1f}',
                    (row['小时'], row['销量(千克)']),
                    xytext=(0, 10),
                    textcoords='offset points',
                    ha='center',
                    fontsize=10,
                    color='#333333')

    # 设置标题和标签
    ax.set_title(f'{date.year}年{date.month}月{date.day}日当天销量趋势图', fontsize=14)
    ax.set_xlabel('时间', fontsize=12)
    ax.set_ylabel('销售量(千克)', fontsize=12)

    # 设置X轴刻度
    ax.set_xticks(range(9, 23))
    ax.set_xticklabels([f'{h}:00' for h in range(9, 23)], rotation=45, ha='right', fontsize=10)

    # 添加网格线
    ax.grid(True, linestyle='--', alpha=0.3)

    # 添加平均线
    avg_sales = hourly_sales['销量(千克)'].mean()
    ax.axhline(avg_sales, color='b', linestyle='--', linewidth=1.5,
               label=f'平均销量: {avg_sales:.1f}千克')

    # 添加图例
    ax.legend(fontsize=10)

    # 设置Y轴范围
    y_min = max(0, hourly_sales['销量(千克)'].min() * 0.9)
    y_max = hourly_sales['销量(千克)'].max() * 1.15
    ax.set_ylim(y_min, y_max)

    # 添加时间区间背景色
    for hour in range(9, 23):
        if 9 <= hour < 12:
            color = 'lightyellow'
        elif 12 <= hour < 14:
            color = 'lightcoral'
        elif 14 <= hour < 17:
            color = 'lightblue'
        elif 17 <= hour < 20:
            color = 'lightgreen'
        else:
            color = 'lavender'

        ax.axvspan(hour - 0.5, hour + 0.5, alpha=0.1, color=color)

# 添加整体标题
plt.suptitle('不同日期销售趋势对比 (9:00-22:00)', fontsize=18, y=0.98)

# 调整布局
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.subplots_adjust(hspace=0.3, wspace=0.2)

# 保存图表
save_dir = 'E:/M/MathModel/23国赛C题/ds/销售分析图表'
os.makedirs(save_dir, exist_ok=True)
save_path = os.path.join(save_dir, '四天销售趋势对比.png')
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"\n图表已保存至: {save_path}")

# 显示图表
plt.show()